package cn.rulian.one.file.controller;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import cn.rulian.base.auth.bo.User;
import cn.rulian.base.common.dto.ExcelBook;
import cn.rulian.base.common.dto.ExcelSheet;
import cn.rulian.base.common.dto.Message;
import cn.rulian.base.common.dto.UserInfo;
import cn.rulian.base.common.property.BusinessProperty;
import cn.rulian.base.common.util.xx;
import cn.rulian.base.common.vo.Result;
import cn.rulian.one.file.bo.SharedFile;
import cn.rulian.one.file.service.SharedFileService;
import cn.rulian.one.file.vo.SharedFileVo;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.format.VerticalAlignment;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;

/**
 * 文件管理 Controller
 */

@Controller
@RequestMapping("/one/file/sharedFile")
public class SharedFileController {
	
	private final Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private SharedFileService service;
	
	@Autowired
	BusinessProperty pro; //业务参数
	
	private final String path="one/file/sharedFile_"; //页面基本路径
	
	/**
	 * 文件的下载及存储方式，有两种实现：
	 * one：普通的文件上传下载方式。文件存储采用"年/月/日  + 随机名称"的方式。
	 * two：上传相同，下载时采用另外一个Context指向所存文件，直接存取文件。文件存储采用"年/月/日 /时分秒 + 原始名称"的方式。
	 */
	private String theType = "two";

	/**
	 * 页面基本路径
	 */
	private String getPath()
	{
		return path;
	}
	
	/**
	 * 列表页面(共享)
	 */
	@RequestMapping("/listPage")
	public String listPage(Model model, HttpServletRequest request) {
		
		String url = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		String urlHost = url.substring(0,url.indexOf(contextPath + "/one/file/sharedFile")); //当前应用的主机目录，如：http://127.0.0.1:8080
		model.addAttribute("urlHost", urlHost);

		model.addAttribute("fileType", SharedFile.TYPE_SHARE); //文件类型
		model.addAttribute("theType", theType); // 文件的下载及存储方式
		
		return this.getPath()+"list";
	}
	
	/**
	 * 列表页面(共享查看)
	 */
	@RequestMapping("/listPageShow")
	public String listPageShow(Model model,HttpServletRequest request) {
		
		String url = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		String urlHost = url.substring(0,url.indexOf(contextPath+ "/one/file/sharedFile")); //当前应用的主机目录，如：http://127.0.0.1:8080
		model.addAttribute("urlHost", urlHost);

		model.addAttribute("fileType", SharedFile.TYPE_SHARE); //文件类型
		model.addAttribute("theType", theType); // 文件的下载及存储方式
		
		return this.getPath()+"listShow";
	}
	
	/**
	 * 列表页面(个人)
	 */
	@RequestMapping("/listPageMy")
	public String listPageMy(Model model,HttpServletRequest request) {
		
		String url = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		String urlHost = url.substring(0,url.indexOf(contextPath+ "/one/file/sharedFile")); //当前应用的主机目录，如：http://127.0.0.1:8080
		model.addAttribute("urlHost", urlHost);

		model.addAttribute("fileType", SharedFile.TYPE_MY); //文件类型
		model.addAttribute("theType", theType); // 文件的下载及存储方式
		
		return this.getPath()+"list";
	}

	/**
	 * 查询
	 */
	@RequestMapping("/listData")
	@ResponseBody
	public Result listData( HttpSession session,SharedFileVo vo) {
		return service.query(session,vo);
	}

	/**
	 * 增加页面
	 */
	@RequestMapping("/addPage")
	public String addPage(Model model,String fileType) {

		model.addAttribute("fileType", fileType); //文件类型
		return this.getPath()+"add";
	}

	/**
	 * 增加
	 */
	@RequestMapping("/add")
	public String add(Model model,SharedFile dto, MultipartFile file,HttpSession session) {
		String backPath = this.getPath()+"add";
		Message rm = new Message();
		model.addAttribute("msg", rm);
		model.addAttribute("fileType", dto.getFileType()); //文件类型
		
		try {
        	if (file.isEmpty()) {
				rm.setMsg("文件为空，上传失败！");
				rm.setCode(Message._ERROR);
				return backPath;
	        }
			// 获取文件名
	        String oldFileName = file.getOriginalFilename();
	        if(oldFileName.indexOf("\\")>0)
	        {
	        	oldFileName = oldFileName.substring(oldFileName.lastIndexOf("\\")+1);
	        }
	        
	        log.info("上传的文件名为：" + oldFileName);
	        log.info("文件大小 ：" + file.getSize());
	        String suffixName = oldFileName.substring(oldFileName.lastIndexOf(".")); //获取文件的后缀名
	        
	        //构建存储文件
	        String uploadPath = pro.getFile_upload_path(); //基础路径
	        
	        String filePath = null;
	        String newFileName = null;
	        if("one".equals(theType))
	        {
		        filePath = xx.getDateStr(new Date()).replaceAll("-", "//")+"//"; //年月日
		        newFileName = UUID.randomUUID() + suffixName;
	        }
	        else
	        {
	    		SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
	        	filePath = xx.getDateStr(new Date()).replaceAll("-", "//") + "//" + formatter.format(new Date()) + "//"; //年月日
	        	newFileName = oldFileName;
	        }
	        
	        File dest = new File(uploadPath + filePath + newFileName);
	        //检测是否存在目录
	        if (!dest.getParentFile().exists()) {
	            dest.getParentFile().mkdirs();
	        }
	        
            file.transferTo(dest);
            
            //取当前用户
            UserInfo userInfo = UserInfo.getUserInfo(session);
            User user = userInfo.getUser();

            //保存DB
            dto.setShowName(oldFileName);
            dto.setFileName(filePath + newFileName);
            //dto.setFileType(SharedFile.TYPE_SHARE);
            dto.setUserId(user.getId());
            dto.setUserName(user.getName());
            dto.setAddTime(new Date());
            dto.setFileSize(file.getSize());
            service.save(dto);
            
            rm.setMsg("上传成功！");
			rm.setCode(Message._SUCCESS);
			return backPath;
        }catch (Exception e) {
            //e.printStackTrace();
            log.error("======（⊙﹏⊙） 文件上传出错：",e);
        	rm.setMsg("上传失败，异常信息：<br/>" + e.toString());
			rm.setCode(Message._ERROR);
			return backPath;
        }
		
	}
	
	//http://127.0.0.1:8080/hexin/one/file/sharedFile/download?id=22
	//文件下载相关代码
    @RequestMapping("/download")
    public String downloadFile(HttpServletResponse response,Long id) throws UnsupportedEncodingException
    {
    	SharedFile bo = service.findOne(id);
    	if(bo!= null)
    	{
    		String uploadPath = pro.getFile_upload_path(); //基础路径
            File file = new File(uploadPath + bo.getFileName());
            if (file.exists()) {
                response.setContentType("application/force-download");// 设置强制下载不打开
                response.addHeader("Content-Disposition",
                		"attachment;fileName=" +  new String(bo.getShowName().getBytes("gbk"),"iso-8859-1"));//设置文件名
                response.addHeader("Content-Length", bo.getFileSize()+""); 
                
                byte[] buffer = new byte[1024];
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    OutputStream os = response.getOutputStream();
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                    System.out.println("success");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
    	}
        return null;
    }
	
	/**
	 * 修改页面
	 */
	@RequestMapping("/updatePage")
	public String updatePage(Model model, Long id) {
		model.addAttribute("bo", service.findOne(id));
		return this.getPath()+"update";
	}

	/**
	 * 修改
	 */
	@RequestMapping("/update")
	@ResponseBody
	public Message update(SharedFileVo vo,Long id) {
		Message rm = new Message();
		try {
			SharedFile obj = vo.getObj();
			SharedFile bo = service.findOne(id);
			//xx.copyObjectField(obj, bo,"addTime"); //属性值copy
			bo.setFileSort(obj.getFileSort());
			bo.setShowName(obj.getShowName());
			service.save(bo);
			
			rm.setMsg("保存成功！");
			rm.setCode(Message._SUCCESS);
		} catch (Exception e) {
			rm.setMsg("保存失败，异常信息：<br/>" + e.toString());
			rm.setCode(Message._ERROR);
			e.printStackTrace();
		}
		return rm;
	}

	/**
	 * 删除
	 */
	@RequestMapping("/delete")
	@ResponseBody
	public Message delete(Long ids[]) {
		Message rm = new Message();
		try {
			//查询所有要删除的数据
			List<Long> idList = new ArrayList<>();
			for(Long id:ids)
			{
				idList.add(id);
			}
			List<SharedFile> fileList = service.findAll(idList);
			//删除文件、删除数据
			for(SharedFile bo:fileList)
			{
	    		String uploadPath = pro.getFile_upload_path(); //基础路径
	            File file = new File(uploadPath + bo.getFileName());
	            file.delete();
				service.delete(bo);
			}
			
			rm.setMsg("删除成功！");
			rm.setCode(Message._SUCCESS);
		} catch (Exception e) {
			rm.setMsg("删除失败，异常信息：<br/>" + e.toString());
			rm.setCode(Message._ERROR);
			e.printStackTrace();
		}
		return rm;
	}
	
	/**
	 * 详情页面
	 */
	@RequestMapping("/detailPage")
	public String detailPage(Model model, Long id) {
		model.addAttribute("bo", service.findOne(id));
		return this.getPath()+"detail";
	}

	/**
	 * 导出Excel
	 * @throws Exception 
	 */
	@RequestMapping("/exportExcel")
	public void exportExcel(HttpServletResponse response,SharedFileVo vo,String type) throws Exception {
		
		File file = new File("aaa.xls");
		jxl.write.WritableWorkbook book = Workbook.createWorkbook(file); //工作薄

		List<SharedFile> allDataList=service.QueryExcelData(vo); //取得导出数据
		ExcelBook<SharedFile> excelBook = this.buildExcelData(allDataList, type); //按维度进行数据加工
		String bookName = excelBook.getName(); //Excel文件名称
		List<ExcelSheet<SharedFile>> sheetList = excelBook.getSheetList(); //各Sheet列表
		if(sheetList!=null && sheetList.size() > 0)
		{
			for(ExcelSheet<SharedFile> excelSheet:sheetList)
			{
				String sheetName = excelSheet.getName(); //名称
				List<SharedFile> oneList = excelSheet.getDataList(); //数据列表
				
				jxl.write.WritableSheet sheet = book.createSheet(sheetName, 0); //工作表
				
				//设置行高
				sheet.getSettings().setDefaultRowHeight(350); //设置所有行默认行高
				sheet.setRowView(0, 700);//第1行 高度
				sheet.setRowView(1, 400);//第2行 高度
				
				//设置个别列宽
				//sheet.setColumnView(2, 12);//宽度设置
				
				//定义格式
				//主标题格式
				WritableCellFormat formatterTitle= new WritableCellFormat(); //标题格式
				formatterTitle.setAlignment(Alignment.CENTRE);//水平对齐
				formatterTitle.setVerticalAlignment(VerticalAlignment.CENTRE);//垂直对齐
				//WritableFont font = new WritableFont(WritableFont.createFont("ＭＳ Ｐゴシック"), 18, WritableFont.BOLD, false); //黑体
				WritableFont font = new WritableFont(WritableFont.TAHOMA, 18, WritableFont.BOLD, false);
				formatterTitle.setFont(font);
				
				//列标题格式
				WritableCellFormat formatterColumnTitle= new WritableCellFormat(); //列标题格式
				formatterColumnTitle.setAlignment(Alignment.CENTRE);//水平对齐
				formatterColumnTitle.setVerticalAlignment(VerticalAlignment.CENTRE);//垂直对齐
				formatterColumnTitle .setBackground(Colour.GRAY_25);//背景色
				formatterColumnTitle.setBorder(Border.ALL, BorderLineStyle.THIN);//边框线  所有边框 细线

				//普通内容格式
				WritableCellFormat formatterCon= new WritableCellFormat(); //内容格式
				formatterCon.setAlignment(Alignment.CENTRE);//水平对齐
				formatterCon.setVerticalAlignment(VerticalAlignment.CENTRE);//垂直对齐
				formatterCon.setBorder(Border.ALL, BorderLineStyle.THIN);//边框线  所有边框 细线
				
				//合计行格式
				WritableCellFormat formatterSum= new WritableCellFormat(); //合计格式
				formatterSum.setAlignment(Alignment.CENTRE);//水平对齐
				formatterSum.setVerticalAlignment(VerticalAlignment.CENTRE);//垂直对齐
				formatterSum.setBorder(Border.ALL, BorderLineStyle.THIN);//边框线  所有边框 细线
				WritableFont font_sum = new WritableFont(WritableFont.TAHOMA, 10, WritableFont.BOLD, false);
				formatterSum.setFont(font_sum);
				
				//输出标题
				sheet.mergeCells(0, 0, 5, 0); //合并单元格（标题）
				sheet.addCell(creatLabel(0,0,"文件管理（"+sheetName+"）",formatterTitle));

				//输出列标题
				int rowNum=1; //行号
				int columnNum=0; //列号
				
				sheet.addCell(creatLabel(rowNum,columnNum++,"序号",formatterColumnTitle));
				sheet.addCell(creatLabel(rowNum,columnNum++,"类别",formatterColumnTitle));
				sheet.addCell(creatLabel(rowNum,columnNum++,"文件名称",formatterColumnTitle));
				sheet.addCell(creatLabel(rowNum,columnNum++,"上传用户",formatterColumnTitle));
				sheet.addCell(creatLabel(rowNum,columnNum++,"上传时间",formatterColumnTitle));
				sheet.addCell(creatLabel(rowNum,columnNum++,"URL",formatterColumnTitle));
				
				//合计项
			
				if(oneList != null && oneList.size() > 0)
				{
					SimpleDateFormat formatterDate = new SimpleDateFormat("yyyy-MM-dd"); //日期格式化
					//SimpleDateFormat formatterTime = new SimpleDateFormat("yyyy-MM-dd HH:mm"); //时间格式化
					//SimpleDateFormat formatterTime2 = new SimpleDateFormat("yyyy-MM-dd HH:mm"); //时间格式化2
					
					//展示数据
					String fileSortStr = ""; // 类别
					String showNameStr = ""; // 文件名称
					String userNameStr = ""; // 上传用户
					String addTimeStr = ""; // 上传时间
					String fileNameStr = ""; // URL
					
					for(int i = 0; i < oneList.size(); i++)
			    	{
						SharedFile bo = oneList.get(i); 
						rowNum++;
						columnNum=0;
						
						//展示数据初始化
						fileSortStr = ""; // 类别
						showNameStr = ""; // 文件名称
						userNameStr = ""; // 上传用户
						addTimeStr = ""; // 上传时间
						fileNameStr = ""; // URL
						
						//展示数据赋值
						if(bo.getFileSort() != null){	fileSortStr = bo.getFileSort().getName();	} //类别
						if(bo.getShowName() != null){	showNameStr = bo.getShowName().toString();	} //文件名称
						if(bo.getUserName() != null){	userNameStr = bo.getUserName().toString();	} //上传用户
						if(bo.getAddTime() != null){	addTimeStr = formatterDate.format(bo.getAddTime());	} //上传时间
						if(bo.getFileName() != null){	fileNameStr = bo.getFileName().toString();	} //URL
						
						//输出一行数据
			    		sheet.addCell(creatLabel(rowNum,columnNum++,(i+1)+"",formatterCon)); 
			    		sheet.addCell(creatLabel(rowNum,columnNum++,fileSortStr ,formatterCon)); // 类别
			    		sheet.addCell(creatLabel(rowNum,columnNum++,showNameStr ,formatterCon)); // 文件名称
			    		sheet.addCell(creatLabel(rowNum,columnNum++,userNameStr ,formatterCon)); // 上传用户
			    		sheet.addCell(creatLabel(rowNum,columnNum++,addTimeStr ,formatterCon)); // 上传时间
			    		sheet.addCell(creatLabel(rowNum,columnNum++,fileNameStr ,formatterCon)); // URL
			    		
			    		//合计项累加
			    	}
					
					//表格增加合计项
					rowNum++;
					columnNum = 0;
					sheet.setRowView(rowNum, 400);//合计行 高度
		    		
		    		sheet.addCell(creatLabel(rowNum,columnNum++,"",formatterSum)); 
		    		sheet.addCell(creatLabel(rowNum,columnNum++,"" ,formatterSum)); // 类别
		    		sheet.addCell(creatLabel(rowNum,columnNum++,"" ,formatterSum)); // 文件名称
		    		sheet.addCell(creatLabel(rowNum,columnNum++,"" ,formatterSum)); // 上传用户
		    		sheet.addCell(creatLabel(rowNum,columnNum++,"" ,formatterSum)); // 上传时间
		    		sheet.addCell(creatLabel(rowNum,columnNum++,"" ,formatterSum)); // URL
    		
				}
			}
		}
		
		//-------------------------------

		book.write();
		book.close();

		FileInputStream f = new FileInputStream(file);
		byte[] fb = new byte[f.available()];
		f.read(fb);
		response.setHeader("Content-disposition", "attachment; filename=" + new String((bookName + ".xls").getBytes("gb2312"), "iso8859-1"));
		ByteArrayInputStream bais = new ByteArrayInputStream(fb);
		int b;
		while ((b = bais.read()) != -1)
		{
			response.getOutputStream().write(b);
		}
		response.getOutputStream().flush();
		f.close();
		
	}
	
	private Label creatLabel(int rowNum,int columnNum,String con,WritableCellFormat formatter) //行，列，内容 ，格式化
	{  
		 return new Label(columnNum, rowNum, con,formatter);   
	}  
	
	/**
	 * 从不同维度，构建Excel导出所需要的数据
	 */
	private ExcelBook<SharedFile> buildExcelData(List<SharedFile> list,String exportType)
	{
		ExcelBook<SharedFile> book = new ExcelBook<SharedFile>();
		
		
		if("all".equals(exportType))
		{//不分表
			book.setName("文件管理");
		}

		//根据维度（sheetName）不同，对数据分表
		Map<String,List<SharedFile>> map =new HashMap<String,List<SharedFile>>(); 
		String sheetName = null;
		for(SharedFile bo:list)
		{
		
	
			if("all".equals(exportType))
			{//不分表
				sheetName="全部";
			}
			
			List<SharedFile> dataList = map.get(sheetName);
			if(dataList==null)
			{
				dataList = new ArrayList<>();
			}
			dataList.add(bo);
			map.put(sheetName, dataList);
		}
		
		//转换Map,得到数据表列表
		List<ExcelSheet<SharedFile>> sheetList = new ArrayList<>();
		for (Map.Entry<String, List<SharedFile>> m : map.entrySet()) 
		{
			ExcelSheet<SharedFile> sheet = new ExcelSheet<SharedFile>();
			sheet.setName(m.getKey());
			sheet.setDataList(m.getValue());
			sheetList.add(sheet);
		} 
		
		if(sheetList.size()==0)
		{
			ExcelSheet<SharedFile> sheet = new ExcelSheet<SharedFile>();
			sheet.setName("全部");
			sheet.setDataList(new ArrayList<SharedFile>());
			sheetList.add(sheet);
		}
		
		book.setSheetList(sheetList);
		
		return book;
	}
	
}
